package com.nexgo.payment.trans.setting.terminalkey.dowmtmk;

import android.support.annotation.NonNull;

import com.nexgo.common.ByteUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.AlgorithmModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.PinPad;
import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity;
import com.nexgo.oaf.apiv3.device.serialport.SerialPortDriver;
import com.nexgo.oaf.apiv3.hsm.HSMDevice;
import com.nexgo.payment.api.ApiDeviceEngine;
import com.nexgo.payment.constrant.PreferencesConstants;
import com.nexgo.payment.databases.DataSource;
import com.nexgo.payment.util.ByteUtil;
import com.nexgo.payment.util.LenType;
import com.nexgo.payment.util.StringUtils;
import com.xinguodu.ddiinterface.Ddi;
import com.xinguodu.ddiinterface.DdiConstant;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Formatter;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Created by wzp on 2018/3/24.
 */

public class TmkDownload {
    private PinPad mPinPad;
    private final DataSource mRepository;
    private SerialPortDriver mSerialPortDriver;
    private int Keyindex;
    private Logger mLog = LoggerFactory.getLogger(TmkDownload.class.getSimpleName());
    private HSMDevice mHSMDevice;
    private static final int secretMode = 0x80000000;


    public TmkDownload(@NonNull DataSource repository){
        mRepository = checkNotNull(repository);
        mPinPad = ApiDeviceEngine.getInstance().getPinPad();
        mHSMDevice = ApiDeviceEngine.getInstance().getHSMDevice();
        Keyindex = Integer.parseInt(StringUtils.firstNonEmpty(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_INDEX),"0"));
        if ("2".equals(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_ALGORITHM))){
            mPinPad.setAlgorithmMode(AlgorithmModeEnum.SM4);
        }else{
            mPinPad.setAlgorithmMode(AlgorithmModeEnum.DES);
        }
    }


    public void cancelLoadKey(){
        quitUpdateTmk(mSerialPortDriver);
        return;
    }

    private int updateBccMkeyNew(byte[] data){
        mLog.debug("data.length {}  data{}",data.length,ByteUtils.byteArray2HexString(data));
        int offset = 0;
        int bankPkLen = ByteUtil.bytes2Int(data,0,2, LenType.BCD);
        offset += 2;

        byte[] bankPk = Arrays.copyOfRange(data,offset, offset + bankPkLen);
        offset += bankPkLen;
        mLog.debug("bankPkLen {}  bankPk {}",bankPkLen,ByteUtils.byteArray2HexString(bankPk));


        int signPkBankLen = ByteUtil.bytes2Int(data, offset,2, LenType.BCD);
        offset += 2;
        byte[] signPkBank = Arrays.copyOfRange(data,offset, offset + signPkBankLen);  //厂商私钥对交行公钥签名值
        offset += signPkBankLen;
        mLog.debug("signPkBankLen {}  signPkBank {}",signPkBankLen,ByteUtils.byteArray2HexString(signPkBank));

        byte[] random = Arrays.copyOfRange(data,offset, offset + 8);
        offset += 8 ;

        mLog.debug("random {} ",ByteUtils.byteArray2HexString(random));

        int signTmkLen = ByteUtil.bytes2Int(data, offset,2, LenType.BCD);
        offset += 2;
        byte[] signTmk = Arrays.copyOfRange(data,offset, offset + signTmkLen);  //交行私钥对 8位随机数+ 主密钥密文的签名
        offset += signTmkLen;
        mLog.debug("signTmkLen {}  signTmk {}",signTmkLen,ByteUtils.byteArray2HexString(signTmk));

        int encryptTmkLen = ByteUtil.bytes2Int(data, offset,2, LenType.BCD);
        offset += 2;
        byte[] encryptTmk = Arrays.copyOfRange(data,offset, offset + encryptTmkLen);  //主密钥密文
        offset += encryptTmkLen;
        mLog.debug("encryptTmkLen {}  encryptTmk {}",encryptTmkLen,ByteUtils.byteArray2HexString(encryptTmk));

        int ckvLen = ByteUtil.bytes2Int(data,offset  ,1, LenType.BCD);
        offset += 1;
        byte[] ckv = Arrays.copyOfRange(data,offset,offset + ckvLen);
        mLog.debug("ckvLen {} \n ckv {}",ckvLen,ByteUtils.byteArray2HexString(ckv));

        byte[] inData = new byte[2048];
        int inLen = 0;
        int Type ;
        if ("2".equals(mRepository.getParamValue(PreferencesConstants.MASTER_KEY_ALGORITHM))){
            Type = AlgorithmModeEnum.SM4.ordinal();
        }else{
            Type = AlgorithmModeEnum.DES.ordinal();
        }
        byte[] type = ByteUtil.int2Hex(Type,4,false);
        System.arraycopy(type,0,inData, inLen,type.length);
        inLen += type.length;
        mLog.debug("type {}",ByteUtils.byteArray2HexString(type));
        byte[] key = ByteUtil.int2Hex(Keyindex,4,false);
        System.arraycopy(key,0,inData, inLen,key.length);
        inLen += key.length;
        mLog.debug("Type {} Keyindex {} ",Type,Keyindex);
        mLog.debug("key {}",ByteUtils.byteArray2HexString(key));
        System.arraycopy(random,0,inData, inLen,random.length);
        inLen += random.length;
        mLog.debug("offset {}",inLen);
        System.arraycopy(encryptTmk,0,inData, inLen,encryptTmk.length);
        inLen += encryptTmk.length;
        mLog.debug("offset {}",inLen);
        System.arraycopy(signTmk,0,inData, inLen,signTmk.length);
        inLen += signTmk.length;
        mLog.debug("offset {}",inLen);
        System.arraycopy(bankPk,0,inData, inLen,bankPk.length);
        inLen += bankPk.length;
        mLog.debug("offset {}",inLen);
        System.arraycopy(signPkBank,0,inData, inLen,signPkBank.length);
        inLen += signPkBank.length;
        mLog.debug("offset {}",inLen);
        mLog.debug("inData {}",ByteUtils.byteArray2HexString(inData));
        int result = writeTmk(Keyindex,inLen,inData);
        if(result != DdiConstant.DDI_OK){
            mLog.debug("writeTmk result {}",result);
            return SdkResult.Fail;
        }
        result = checkBccKey(ckv,ckvLen);
        mLog.debug("checkBccKey result {}",result);
        return result;
    }

    private int checkBccKey(byte[] checkValue, int checkValueLen ){
        byte[] data = new byte[8];

 /*       if(checkValueLen > 8)
            return SdkResult.Fail;*/

        Arrays.fill(data, (byte)0x00);
        byte[] calcCheckValue = mPinPad.encryptByMKey(Keyindex, data ,data.length);
        if(calcCheckValue == null) return SdkResult.Fail;
        mLog.debug("checkBccKey value {}", ByteUtils.byteArray2HexString(checkValue));
        mLog.debug("checkBccKey calc check value {}", ByteUtils.byteArray2HexString(calcCheckValue));
        return byteArrayCompare(calcCheckValue, 0, checkValue, 0, checkValueLen)? SdkResult.Success:SdkResult.Fail;
    }

    private int writeTmk(int keyIndex ,int inLen ,byte[] inData ){
        int result;
        int[] devHandle = new int[1];
        int mode = 0;
        int[] outLen = new int[1];
        byte[] outData = new byte[16];
        result = Ddi.ddi_pinpad_opendevice(mode ,devHandle );
        if(result != DdiConstant.DDI_OK) return result;
        result = Ddi.ddi_customer_cmddeal(1,inLen,inData,outLen,outData);
        if(result != DdiConstant.DDI_OK) {
            mLog.debug("result {}",result);
            Ddi.ddi_pinpad_closedevice(mode,devHandle);
        }
        mLog.debug("outLen {} outData{}",outLen , ByteUtils.byteArray2HexString(outData));
        return result;
    }

    private byte[] readBccIndexVer( int cmd){
        int result;
        int[] devHandle = new int[1];
        int mode = 0;
        int[] outLen = new int[1];
        byte[] outData = new byte[16];
        result = Ddi.ddi_pinpad_opendevice(mode ,devHandle );
        if(result != DdiConstant.DDI_OK) return null;
        mLog.debug("readBccIndexVer  index {}" , cmd);
        result = Ddi.ddi_read_custom_info(cmd,outData,outLen);
        Ddi.ddi_pinpad_closedevice(mode,devHandle);
        if(result != DdiConstant.DDI_OK) { mLog.debug("result ={}",result);return null;}
        mLog.debug("outLen {},outData {}",outLen[0],ByteUtils.byteArray2HexString(outData));
        return Arrays.copyOfRange(outData,0,outLen[0]);
    }

    private byte[] bccKeyExchange(){
        int result;
        int[] devHandle = new int[1];
        int mode = 0;
        int[] outLen = new int[1];
        byte[] outData = new byte[1024];
        byte[] inData = new byte[0];
        int inLen = 0;
        result = Ddi.ddi_pinpad_opendevice(mode ,devHandle );
        if(result != DdiConstant.DDI_OK) return null;
        result = Ddi.ddi_customer_cmddeal(0,inLen,inData,outLen,outData);
        Ddi.ddi_pinpad_closedevice(mode,devHandle);
        if(result != DdiConstant.DDI_OK) {
            mLog.debug("result ={}",result);return null;
        }
        mLog.debug("outLen {},outData {}",outLen[0],ByteUtils.byteArray2HexString(outData));
        return Arrays.copyOfRange(outData,0,outLen[0]);
    }

    private byte[] formBccRsaSignMsg(){
        mLog.debug("formBccRsaSignMsg");

        String FRSA = "KRSA";
        String bit = "2048";
        String mode = "65537";

        byte[] sNumber = readBccIndexVer(0);
        if(sNumber == null){
            mLog.error("sNumber null");
            return null;
        }
        byte[] version = readBccIndexVer(1);
        if(version == null){
            mLog.error("version null");
            return null;
        }
        mLog.debug("sNumber {} version {}",new String(sNumber),new String(version));

        byte[] exchangeData = bccKeyExchange();
        if(exchangeData == null || exchangeData.length != 520){
            mLog.error("exchangeData error");
            return null;
        }
        mLog.debug("exchangeData {}",ByteUtils.byteArray2HexString(exchangeData));
        int offset = 0;
        byte[] random = Arrays.copyOfRange(exchangeData , offset , 8);
        offset += 8;
        mLog.debug("random {}",ByteUtils.byteArray2HexString(random));
        byte[] pkEpp = Arrays.copyOfRange(exchangeData , offset , offset + 256);
        offset += 256;
        mLog.debug("pkEpp {}",ByteUtils.byteArray2HexString(pkEpp));
        byte[] signPk = Arrays.copyOfRange(exchangeData , offset , offset + 256);
        offset += 256;
        mLog.debug("signPk {}",ByteUtils.byteArray2HexString(signPk));

        int len = 0;
        byte[] tmpData = new byte[2048];
        len += 8 ; //预留8个字节长度为
        System.arraycopy(FRSA.getBytes(), 0, tmpData, len, FRSA.length());
        len += FRSA.length();
        System.arraycopy(FRSA.getBytes(), 0, tmpData, len, FRSA.length());
        //长度
        String pkLen = new Formatter().format("%04d", pkEpp.length).toString();
        System.arraycopy(ByteUtil.string2ASCIIByteArray(pkLen), 0, tmpData, len, pkLen.length());
        len += pkLen.length();
        System.arraycopy(pkEpp, 0, tmpData, len, pkEpp.length);
        len += pkEpp.length;
        System.arraycopy(bit.getBytes(), 0, tmpData, len, bit.length());
        len += bit.length();
        System.arraycopy(mode.getBytes(), 0, tmpData, len, mode.length());
        len += mode.length();
        String signLen = new Formatter().format("%04d", signPk.length).toString();
        System.arraycopy(ByteUtil.string2ASCIIByteArray(signLen), 0, tmpData, len, signLen.length());
        len += signLen.length();
        System.arraycopy(signPk, 0, tmpData, len, signPk.length);
        len += signPk.length;
        tmpData[len ++] = 0x31;
        System.arraycopy(sNumber, 0, tmpData, len, sNumber.length);
        len += sNumber.length;
        System.arraycopy(random, 0, tmpData, len, random.length);
        len += random.length;
        System.arraycopy(version, 0, tmpData, len, version.length);
        len += version.length;
        tmpData[len ++ ] = 0x00;
        String total_len  = new Formatter().format("%08d", len - 8).toString();
        System.arraycopy(ByteUtil.string2ASCIIByteArray(total_len), 0, tmpData, 0, total_len.length());
        mLog.debug("need send total len {}",len);

        return Arrays.copyOfRange(tmpData,0,len);

    }

    private int initSerialPort(int portNo){
        mLog.debug("initSerialPort");
        int ret = -1;
        SerialCfgEntity cfgEntity = new SerialCfgEntity();
        mSerialPortDriver = ApiDeviceEngine.getInstance().getSerialPortDriver(portNo);
        try{
            mSerialPortDriver.disconnect();
            cfgEntity.setBaudRate(9600);
            cfgEntity.setParity('n');
            cfgEntity.setDataBits(8);
            cfgEntity.setStopBits(1);
            ret = mSerialPortDriver.connect(cfgEntity);
            if(ret != SdkResult.Success  ){
                mLog.error(" initSerialPort err{} ", ret);
                return ret;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        mLog.error("initSerialPort");
        return ret ;
    }

    private byte[] reFormSendBag(byte[] data ,boolean bfinal){
        byte[] msg = new byte[256];
        int offset = 0 ;
        byte lrc = 0x00;
        byte[] buf ;
        msg[offset++] = 0x02;
        System.arraycopy(ByteUtil.int2MBCD(data.length + 14 ,2), 0 ,msg ,offset,2);
        offset += 2;
        buf = mRepository.getParamValue(PreferencesConstants.TRACE_NUMBER).getBytes();
        System.arraycopy(buf, 0, msg, offset, 6);
        offset += 6;
        buf = mRepository.getParamValue(PreferencesConstants.TERMINAL_ID).getBytes();
        System.arraycopy(buf, 0, msg, offset, 8);
        offset += 8;
        System.arraycopy(data, 0, msg, offset, data.length);
        offset += data.length;
        msg[offset++] =(byte) (bfinal? 1 :0);
        msg[offset++] = 0x03;
        for(int i = 1; i < offset; i++){
            lrc ^= msg[i];
        }
        msg[offset++] = lrc;
        return Arrays.copyOfRange(msg,0,offset);
    }

    private int sendRequest(byte[] buf){
        int ret = SdkResult.Fail;
        byte[] tmp;
        byte[] sendMsg;
        byte[] recv = new byte[32];
        byte[] recvtotal = new byte[32];
        boolean bOver ;
        int page = (buf.length + 235)/236;
        for (int i = 0 ;i < page ; i ++) {
            bOver = (i == (page - 1));
            int len = 236 * (i+1) > buf.length ? buf.length : 236 * (i+1);
            tmp  = Arrays.copyOfRange(buf, 236 * i, len);
            mLog.debug("len {} is over {} ,236 * i {} i {}",len , i == (page - 1),  236 * i , i);
            mLog.debug("tmp.length {} \n tmp {}", tmp.length, ByteUtils.byteArray2HexString(tmp));
            sendMsg = reFormSendBag(tmp, i == (page - 1));
            mLog.debug("sendMsg.length {} \n sendMsg {}", sendMsg.length, ByteUtils.byteArray2HexString(sendMsg));
            ret = mSerialPortDriver.send(sendMsg, sendMsg.length);
            if (ret < 0) {
                mLog.debug("recv err {}", ret);
                break;
            }
            //最后一包外面接收
            if(bOver )
            {
                mLog.debug("开始接受密钥数据");
                ret = SdkResult.Success;
                break;
            }
            int recvLen = 0;
            int totalLen = 0;
            while(true){
                ret = mSerialPortDriver.recv(recv, recv.length, 10 * 1000);
                if (ret < 0) {
                    mLog.debug("recv err {}", ret);
                    ret =  SdkResult.Fail;
                    break;
                } else {
                    //判断是否继续上送
                    // 第一包
                    if (recvLen == 0) {   //第一次收到数据
                        if (recv[recvLen] != 0x02) {
                            ret = SdkResult.Fail;
                            mLog.debug("recv[recvLen] != 0x02");
                            break;
                        }
                        byte lenDate[] = new byte[2];
                        System.arraycopy(recv, 1, lenDate, 0, 2);  //跳过第一个字节 0x02
                        totalLen = ByteUtils.bcdByteArray2Int(lenDate);
                    }
                    System.arraycopy(recv, 0, recvtotal, recvLen, ret);
                    recvLen += ret;
                    mLog.debug("totalLen {} recvLen{} recvtotal{}",totalLen,recvLen,ByteUtils.byteArray2HexString(recvtotal));
                    if (recvLen >= totalLen + 5) {
                        byte response[] = new byte[2];
                        System.arraycopy(recvtotal, 3, response, 0, totalLen);  //跳过第一个字节 0x02
                        mLog.debug("response {}",ByteUtils.byteArray2HexString(response));
                        if (!"3030".equals(ByteUtils.byteArray2HexString(response))) {
                            mLog.debug("返回错误");
                            ret = SdkResult.Fail;
                            break;
                        }else{
                            mLog.debug("当前数据处理完毕");
                            break;
                        }
                    }
                }
            }
            //失败或者最后一包退出
            if(ret == SdkResult.Fail)
            {
                mLog.debug("接受密钥数据失败");
                break;
            }
        }
        return ret;
    }

    private int sendRequest2(byte[] buf){
       int ret = SdkResult.Fail;
       byte[] tmp;
       byte[] sendMsg;
       byte[] recv = new byte[32];
       boolean bOver ;
       int page = (buf.length + 235)/236;
       for (int i = 0 ;i < page ; i ++) {
           bOver = (i == (page - 1));
           int len = 236 * (i+1) > buf.length ? buf.length : 236 * (i+1);
           tmp  = Arrays.copyOfRange(buf, 236 * i, len);
           mLog.debug("len {} is over {} ,236 * i {} i {}",len , i == (page - 1),  236 * i , i);
           mLog.debug("tmp.length {} \n tmp {}", tmp.length, ByteUtils.byteArray2HexString(tmp));
           sendMsg = reFormSendBag(tmp, i == (page - 1));
           mLog.debug("sendMsg.length {} \n sendMsg {}", sendMsg.length, ByteUtils.byteArray2HexString(sendMsg));
           ret = mSerialPortDriver.send(sendMsg, sendMsg.length);
           if (ret < 0) {
               mLog.debug("recv err {}", ret);
               break;
           }
           //最后一包外面接收
           if(bOver )
           {
               mLog.debug("开始接受密钥数据");
               ret = SdkResult.Success;
               break;
           }
           int recvLen = 0;
           int totalLen = 0;
           while(true){
               ret = mSerialPortDriver.recv(recv, recv.length, 10 * 1000);
               if (ret < 0) {
                   mLog.debug("recv err {}", ret);
                   ret =  SdkResult.Fail;
                   break;
               } else {
                   //判断是否继续上送
                    // 第一包
                   if (recvLen == 0) {   //第一次收到数据
                       if (recv[recvLen] != 0x02) {
                           ret = SdkResult.Fail;
                           mLog.debug("recv[recvLen] != 0x02");
                           break;
                       }
                       byte lenDate[] = new byte[2];
                       System.arraycopy(recv, 1, lenDate, 0, 2);  //跳过第一个字节 0x02
                       totalLen = ByteUtils.bcdByteArray2Int(lenDate);
                   }
                   recvLen += ret;
                   mLog.debug("totalLen {} recvLen{} recv{}",totalLen,recvLen,ByteUtils.byteArray2HexString(recv));
                   if (recvLen >= totalLen + 5) {
                       byte response[] = new byte[2];
                       System.arraycopy(recv, 3, response, 0, totalLen);  //跳过第一个字节 0x02
                       mLog.debug("response {}",ByteUtils.byteArray2HexString(response));
                       if (!"3030".equals(ByteUtils.byteArray2HexString(response))) {
                           mLog.debug("返回错误");
                           ret = SdkResult.Fail;
                           break;
                       }else{
                           mLog.debug("当前数据处理完毕");
                           break;
                       }
                   }
               }
           }
           //失败或者最后一包退出
           if(ret == SdkResult.Fail)
           {
               mLog.debug("接受密钥数据失败");
               break;
           }
       }
       return ret;
    }
    private byte[] formRequest(byte[] data){
        byte msg[] = new  byte[16];
        int offset =0 ;
        byte lrc = 0x00;
        msg[offset++] = 0x02;
        msg[offset++] = 0x00;
        msg[offset++] = 0x02;
        System.arraycopy(data, 0, msg, offset, 2);
        offset += 2;
        msg[offset++] = 0x03;
        for(int i = 1; i < offset; i++){
            lrc ^= msg[i];
        }
        msg[offset] = lrc;
        return msg;
    }
    private byte[] recvResponse(){
        int ret = 0;
        byte buf[] = new byte[256];
        int totalLen = 0 ,recvLen = 0;
        boolean bOver = false; //
        boolean bfinish = false;
        int tmkLen = 0;
        byte[] tmk = new byte[2048];
        int i = 0;
        mLog.debug("recvResponse");

        byte response[] = new byte[2];
        byte[] recv = new byte[256];
        while(true) {
            ret = mSerialPortDriver.recv(buf, buf.length, 10*1000);
            if (ret < 0) {
                mLog.debug("recv err {}", ret);
//                quitUpdateTmk(mSerialPortDriver);
                return null;
            } else {
                if (recvLen == 0) {   //第一次收到数据
                    if (buf[recvLen] != 0x02) {
                        mLog.debug("ret {}buf {} ",ret,ByteUtils.byteArray2HexString(buf));
                        mLog.debug("recv[0]  != 0x02");
                        return null;
                    }
                    byte lenDate[] = new byte[2];
                    System.arraycopy(buf, 1, lenDate, 0, 2);  //跳过第一个字节 0x02
                    totalLen = ByteUtils.bcdByteArray2Int(lenDate);
                }
                System.arraycopy(buf, 0, recv, recvLen, ret);
                recvLen += ret;
                mLog.debug("totalLen {} recvLen{}",totalLen,recvLen );
                if (recvLen >= totalLen + 5) { //当前包数据收完
                    mLog.debug("recv {}",ByteUtils.byteArray2HexString(recv));
                    System.arraycopy(recv, 3, response, 0, 2);  //跳过第一个字节 0x02 2个字节长度获取应答码
                    mLog.debug("recv[recvLen -2] {} recv[recvLen -3] {}",recv[recvLen - 2],recv[recvLen -3]);
                    mLog.debug("response {}",ByteUtils.byteArray2HexString(response));
                    if (!"3030".equals(ByteUtils.byteArray2HexString(response))) {
                        mLog.debug("返回错误");
                        ret = SdkResult.Fail;
                    }else{
                        bOver = ( recv[recvLen - 3] == 0x01 );
                        mLog.debug("bOver {}",bOver);
                        //偏移头部分
                        if(tmkLen == 0) {
                            int tmkTotalLen = ByteUtil.MBCD2Int(Arrays.copyOfRange(recv, 19, 21));
                            mLog.debug("tmkTotalLen{}",tmkTotalLen);
                        }
                        int copyLen =  recvLen  - 22;   //去除 后三字节  标识符 + 03 +LRC
                        System.arraycopy(recv, 19 , tmk, tmkLen, copyLen);
                        tmkLen += copyLen;
                        mLog.debug("tmkLen{} copyLen{} "  ,tmkLen ,copyLen);
                        mLog.debug("当前数据处理完毕");
                        bfinish = true;
                    }
                }
            }
            //下载完或者出错
            if(bOver || ret == SdkResult.Fail)
            {
                if( ret == SdkResult.Fail)
                     tmk = null;
                break;
            }
            if(bfinish){ //如果本包收完重新发送请求
                mLog.debug("接收包 i {}  "  ,i);
                i++;
                byte[] sendMsg = formRequest(response);
                mSerialPortDriver.send(sendMsg, sendMsg.length);
                bfinish = false;
                recvLen = 0;
                totalLen = 0;
            }
        }
        return tmk;
    }

    public int requestdownTmk(int portNo, int timeout){
        int ret ;
        byte[] sendData;
        byte[] tmk ;
//        初始化串口
        ret = initSerialPort(portNo);
        if(ret !=  SdkResult.Success){ return  ret;}
//      组包
        sendData = formBccRsaSignMsg();
        if (sendData == null){return SdkResult.Fail;}
//        分包发送
        mLog.debug("sendData.length {} sendData {}",sendData.length,ByteUtils.byteArray2HexString(sendData));
        ret = sendRequest(sendData);
        if(ret !=  SdkResult.Success){
            quitUpdateTmk(mSerialPortDriver);
            return  ret;
        }
//        发送完之后接收主密钥密文
        tmk = recvResponse();
        if(tmk == null) {
            quitUpdateTmk(mSerialPortDriver);
            return  SdkResult.Fail;
        }
//       解析主密钥更新
        ret = updateBccMkeyNew(tmk);
        if(ret != SdkResult.Success) {
            quitUpdateTmk(mSerialPortDriver);
            return  SdkResult.Fail;
        }
        quitUpdateTmk(mSerialPortDriver);
        return ret;
    }



    private void quitUpdateTmk( SerialPortDriver serialPortDriver)  {
        try {
            serialPortDriver.clrBuffer();
            serialPortDriver.disconnect();
        }catch (Exception e ){
            e.printStackTrace();
        }
    }

    public static boolean byteArrayCompare(byte[] data1, int data1Pos, byte[] data2, int data2Pos, int len) {
        for (int i = 0; i < len; i++) {
            if (data1[data1Pos + i] != data2[data2Pos + i])
                return false;
        }
        return true;
    }
}
